import os
import sys

from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.http import Http404, HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.db.models import Count

from pybo.mylessons.models import Lesson, LessonNode, LessonResult
from pybo.myproblems.models import MySubmitForm, MySubmit, Problem, Result
from pybo.invoker import invoker
from pybo.settings import VERDICT
from pybo.invoker.settings import SANDBOX_PATH, PROBLEMS_PATH

@login_required
def index(request):
    status = LessonResult.objects.filter(user = request.user)
    result = {_.lesson.id: _.status for _ in status}
    if 1 not in result.keys():
        result[1] = 1

    lessons = []
    for les in Lesson.objects.order_by('order'):
        lessons.append({'title': les.title, 'id': les.id, 'status': result.get(les.id, 0)})                         

    return TemplateResponse(request, 'lessons.html', {'lessons': lessons})

def node_up(request, lesson_id, node_id):
    node1 = LessonNode.objects.get(pk=node_id)
    node2 = LessonNode.objects.filter(order__lt=node1.order).order_by('-order')[0]
    node2.order, node1.order = node1.order, node2.order
    node1.save()
    node2.save()
    return HttpResponseRedirect('/lessons/' + str(lesson_id) + '/edit') 

def check_lesson_result(user, lesson_id):
    prev = LessonResult.objects.filter(user = user).filter(lesson__id = lesson_id)
    if not prev or prev[0].status == 1:
        for ln in LessonNode.objects.filter(lesson__id=lesson_id):
            if ln.problem and not Result.objects.filter(problem=ln.problem, user=user):
                break #unsolved problem found
        else:                              
            #all problems solved
            if not prev:
                LessonResult(user=user, lesson=Lesson.objects.get(pk=lesson_id), status = 2).save()                                  
            else:
                prev[0].status = 2
                prev[0].save()

    lesson = Lesson.objects.get(pk=lesson_id)
    new_les = []
    for les in lesson.lesson_set.all():
        if not LessonResult.objects.filter(user=user, lesson=les).count():
            for _ in les.depend.all(): 
                if not LessonResult.objects.filter(lesson=_,user=user,status=2):
                    break
            else:
                res = LessonResult(user=user, lesson=les, status = 1).save()                                  
                new_les += [les]
    return new_les

@login_required
def lesson_noaccess(request, lesson_id):
    try:
        current_lesson = Lesson.objects.get(pk=lesson_id)
    except Lesson.DoesNotExist:
        raise Http404
    deps = []
    for node in current_lesson.depend.all():
        res = LessonResult.objects.filter(user=request.user, lesson=node)
        if not res or res[0].status == 1:
            deps.append(node)
    return TemplateResponse(request, 'noaccess.html', 
           {'deps': deps,})

@login_required
def content(request, lesson_id, edit = False):
    try:
        current_lesson = Lesson.objects.get(pk=lesson_id)
    except Lesson.DoesNotExist:
        raise Http404

    #lesson is not accessible while problems in dependent lessons are not solved
    res = LessonResult.objects.filter(lesson=current_lesson, user=request.user).count()
    if res == 0 and current_lesson.id > 1: #lesson N1 is always available
        return HttpResponseRedirect('/lessons/' + str(lesson_id) + '/noaccess') 

    success = [0] * 5
    new_les = [] 

    if request.method == 'POST': # If the form has been submitted...
        form = MySubmitForm(request.POST) # A form bound to the POST data
        if form.is_valid(): # All validation rules pass
            fcode = open(os.path.join(SANDBOX_PATH,"test.py"), "w")
            fcode.write(form.cleaned_data["code"])
            fcode.close()            
            problem = Problem.objects.get(pk=form.cleaned_data["problem"])
            verdict = invoker.check(Problem.objects.get(pk=form.cleaned_data["problem"]))
            MS = MySubmit(code = form.cleaned_data["code"], problem = problem, verdict = verdict, author = request.user) 
            MS.save()
            if verdict == VERDICT['OK']:
                prev = Result.objects.filter(user = request.user).filter(problem__id = form.cleaned_data["problem"])
                if not prev:
                    Result(user = request.user, problem = problem, score = 1).save()                                  
                new_les = check_lesson_result(request.user, lesson_id)
    contents = []              
    for node in current_lesson.mylessons_lessonnode_related.all():
        if node.problem and node.problem.mysubmit_set.filter(author=request.user).count() > 0:
            code = node.problem.mysubmit_set.filter(author=request.user)[node.problem.mysubmit_set.filter(author=request.user).count() - 1].code
            contents += [{'text': node.text, 
                          'id': node.problem.id, 
                          'verdict': node.problem.mysubmit_set.all()[node.problem.mysubmit_set.count() - 1].get_verdict_display(), 
                          'problem_form' : MySubmitForm({'problem' : node.problem.id, 'code' : code}), 
                          'title' : node.problem.title,
                          'statement' : node.problem.statement,
                          'stub' : node.problem.stub.replace("\r\n","\\n") if node.problem.stub else None,
                          'code' : code.replace("\r\n","\\n"),
                        }]
            success[node.problem.mysubmit_set.all()[node.problem.mysubmit_set.count() - 1].verdict] += 1
        else:
            contents += [{'text': node.text, 
                          'id': node.problem.id if node.problem else None, 
                          'verdict': 0, 
                          'problem_form' : MySubmitForm({'problem' : node.problem.id, 'code' : node.problem.stub if node.problem and node.problem.stub else '#INSERT YOUR CODE HERE'} if node.problem else None) if node.problem else None, 
                          'title' : node.problem.title if node.problem else None,
                          'statement' : node.problem.statement if node.problem else None,
                          'stub' : node.problem.stub.replace("\r\n","\\n") if node.problem else None,
                        }]
            if node.problem:
                success[3] += 1
    prob_number = 1
    for i in range(len(contents)):
        if contents[i]['problem_form']:
            contents[i]['problem_number'] = prob_number
            prob_number += 1
    if edit and request.user.is_authenticated():
        return TemplateResponse(request, 'lesson_edit.html', 
           {'lesson': current_lesson, 'contents' : contents})
    else:
        return TemplateResponse(request, 'lesson.html', 
           {'lesson': current_lesson, 
            'contents': contents, 
            'success': (xrange(success[1]), xrange(success[2]), xrange(success[3]),), 
            'new_les': new_les,
           })
    